package com.example.test.hc;

import cn.hutool.core.io.FileUtil;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;

@Slf4j
public class Main {
    private static final HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
    private static MyFMSGCallBack fMSFCallBack_V31 = null;
    private static HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();

    @SneakyThrows
    public static void main(String[] args) {
        init();
        int userId = login("58.221.101.74", (short) 8000, "admin", "szlx12345"); // 登录

        // 布防
        int lAlarmHandle = setupAlarmChan(userId);

        for (int i = 0; i < 10; i++) {
            Thread.sleep(2000);
            if (!fMSFCallBack_V31.getStack().empty()) {
                System.out.println(fMSFCallBack_V31.getStack().pop());
            }
        }

        // 手动抓拍
//        manualSnap(userId, 1);

        // 设备工作状态
//        HCNetSDK.NET_DVR_WORKSTATE_V30 deviceWorkState = getDeviceWorkState(userId);

        // 撤防
//        closeAlarmChan(lAlarmHandle);

        // TODO: 有问题,都是false
        boolean able = hasAbility(userId, 0x402);


        logout(userId);

        // 清理资源
        hCNetSDK.NET_DVR_Cleanup(); // 释放资源，和NET_DVR_Init相对应
    }

    /**
     * 初始化SDK，调用其他SDK函数的前提
     **/
    public static boolean init() {
        // 设置SDK初始化参数
        HCNetSDK.BYTE_ARRAY byteArray1 = new HCNetSDK.BYTE_ARRAY(256);
        HCNetSDK.BYTE_ARRAY byteArray2 = new HCNetSDK.BYTE_ARRAY(256);

        String libcryptoPath = "F:\\lib\\libcrypto.so";
        String libsslPath = "F:\\lib\\libssl.so";

        // 带有OpenSSL加密库库名的路径，支持1.0.2和1.1.1版本，SDK内部加载库后，自动获取openssl版本
        System.arraycopy(libcryptoPath.getBytes(), 0, byteArray1.byValue, 0, libcryptoPath.length());
        byteArray1.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(3, byteArray1.getPointer());

        // 带有OpenSSL通信库库名的路径，支持1.0.2和1.1.1版本，SDK内部加载库后，自动获取openssl版本
        System.arraycopy(libsslPath.getBytes(), 0, byteArray2.byValue, 0, libsslPath.length());
        byteArray2.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(4, byteArray2.getPointer());

        // 设置组件库加载路径，即HCNetSDK.dll或HCNetSDK.so的路径。sPath可以为绝对路基或相对路径。若为相对路径，相对路径+应用程序可执行路径不超过256
        String libHomePath = "F:\\lib\\";
        HCNetSDK.NET_DVR_LOCAL_SDK_PATH localSDKPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
        System.arraycopy(libHomePath.getBytes(), 0, localSDKPath.sPath, 0, libHomePath.length());
        localSDKPath.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(2, localSDKPath.getPointer());

        hCNetSDK.NET_DVR_SetLogToFile(3, "/", false);
        return hCNetSDK.NET_DVR_Init();
    }

    /**
     * 用户注册设备
     **/
    public static int login(String ip, Short port, String username, String password) {
        int userId = hCNetSDK.NET_DVR_Login_V30(ip, port, username, password, deviceInfo);
        if (userId == -1) {
            log.error("登录失败，错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info("登录成功，userID={}", userId);
        }

        return userId;
    }

    /**
     * 建立报警上传通道，获取报警等信息
     **/
    public static int setupAlarmChan(int userId) {
        if (fMSFCallBack_V31 == null) {
            fMSFCallBack_V31 = new MyFMSGCallBack();
            Pointer pUser = null;
            if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
                log.error("设置回调函数失败");
            } else {
                log.info("设置回调函数成功");
            }
        }

        // 报警布防设置
        HCNetSDK.NET_DVR_SETUPALARM_PARAM setupAlarmParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
        setupAlarmParam.dwSize = setupAlarmParam.size();
        setupAlarmParam.byLevel = 1;  //布防优先级，0-一等级（高），1-二等级（中），2-三等级（低）
        setupAlarmParam.byAlarmInfoType = 1; //上传报警信息类型（抓拍机支持），0-老报警信息（NET_DVR_PLATE_RESULT），1-新报警信息(NET_ITS_PLATE_RESULT)2012-9-28
        setupAlarmParam.byDeployType = 2; //布防类型：0-客户端布防，1-实时布防
        setupAlarmParam.write(); // 将结构体的字段值写入到ThreadLocal中

        int lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(userId, setupAlarmParam);
        if (lAlarmHandle == -1) {
            log.error("布防失败，错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info("布防成功");
        }
        return lAlarmHandle;
    }

    /**
     * 撤销报警上传通道
     **/
    public static boolean closeAlarmChan(int lAlarmHandle) {
        return hCNetSDK.NET_DVR_CloseAlarmChan(lAlarmHandle);
    }

    /**
     * 注销
     **/
    public static void logout(int userId) {
        hCNetSDK.NET_DVR_Logout(userId);
    }

    /**
     * 手动抓拍
     **/
    public static void manualSnap(int userId, int channel) {
        //图片参数
        HCNetSDK.NET_DVR_JPEGPARA param = new HCNetSDK.NET_DVR_JPEGPARA();
        param.wPicSize = 5; // 设置图片的分辨率: 0=CIF, 1=QCIF, 2=D1 3=UXGA(1600x1200), 4=SVGA(800x600), 5=HD720p(1280x720),6=VGA
        param.wPicQuality = 1; // 设置图片质量: 0-最好 1-较好 2-一般

        // 返回结果
        IntByReference lpSizeReturned = new IntByReference(); // size
        byte[] bytes = new byte[1280 * 720]; // 缓冲区
        hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, channel, param, bytes, 1280 * 720, lpSizeReturned);

        String path = String.format("/home/wangbo/%s/%d.jpg", String.format("%tF", new Date()), System.currentTimeMillis());
        FileUtil.writeBytes(bytes, path);
    }

    /**
     * 获取设备工作状态
     **/
    public static HCNetSDK.NET_DVR_WORKSTATE_V30 getDeviceWorkState(int userId) {
        HCNetSDK.NET_DVR_WORKSTATE_V30 deviceWorkState = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        hCNetSDK.NET_DVR_GetDVRWorkState_V30(userId, deviceWorkState);
        return deviceWorkState;
    }

    /**
     * 该设备是否包含指定能力
     **/
    public static boolean hasAbility(int userId,int abilityType) {
        return hCNetSDK.NET_DVR_GetDeviceAbility(userId, abilityType, null, 0, null, 0);
    }
}
